package core

import (
	"bufio"
	"encoding/json"
	"io"
	"log"
	"os"
	"strconv"
	"time"
)

type Task struct {
	TaskID     int
	Level      int
	Type       int
	LoopCnt    int
	DevIDs     []string
	PcmFiles   []int
	EndTime    int64
	CreateTime int64

	Stop bool
}

type TaskStatusMsg struct {
	MsgType int `json:"msgType"`
	TaskID  int `json:"jobId"`
	Code    int `json:"code"`
}

type PlayFileMsg struct {
	MsgType     int `json:"msgType"`
	TaskID      int `json:"jobId"`
	AudioFileID int `json:"audioFileId"`
}

func (t *Task) Run() {
	ctx := GetCtx()

	// defer, do clean
	defer func() {
		// release dev
		for _, devID := range t.DevIDs {
			dev := ctx.DevCache[devID]
			if dev != nil {
				if dev.CurrentTask == t {
					dev.CurrentTask = nil
				}
			}
		}

		// remove task cache
		delete(ctx.TaskCache, t.TaskID)

		// send tcp complete msg
		msg := &TaskStatusMsg{
			MsgType: 2,
			TaskID:  t.TaskID,
			Code:    2,
		}
		b, _ := json.Marshal(msg)
		ctx.S1.Broadcast(b)
	}()

	// send task start msg, did in net1 ?
	// ...

	// open sound
	for _, devID := range t.DevIDs {
		dev := ctx.DevCache[devID]
		if dev != nil && !dev.Locked && dev.CurrentTask == nil {
			dev.CurrentTask = t
			// send 3 times ?
			dev.OpenSound()
			dev.OpenSound()
			dev.OpenSound()
		}
	}

	time.Sleep(time.Second * 1)

	if t.Type == 3 && t.EndTime > 0 {
		for !t.Stop {
			if time.Now().Unix()/1e6 > t.EndTime {
				break
			}
			t.playFileList()
		}
	} else if t.Type == 2 && t.LoopCnt != 0 {
		for i := 0; i < t.LoopCnt && !t.Stop; i++ {
			t.playFileList()
		}
	} else {
		t.playFileList()
	}
}

func (t *Task) playFileList() {
	for i, fID := range t.PcmFiles {
		// send current playing file msg
		msg := &PlayFileMsg{
			MsgType:     4,
			TaskID:      t.TaskID,
			AudioFileID: i,
		}
		b, _ := json.Marshal(msg)
		ctx.S1.Broadcast(b)

		if t.Stop {
			return
		}

		f, err := os.Open(ctx.Conf.AudioFilePath + string(os.PathSeparator) + strconv.Itoa(fID))
		if err != nil {
			log.Println("open file err", err)
			continue
		}
		defer f.Close()

		// send tcp play file index msg
		log.Println(i)

		br := bufio.NewReader(f)
		buf := make([]byte, 512)

		data := make([]byte, 520)
		data[0] = 0xaa
		data[1] = 0x00
		data[2] = 0x00
		data[3] = 0x00

		keepGoing := true
		for keepGoing && !t.Stop {
			now := time.Now().Unix() / 1e6

			if t.EndTime != 0 && now > t.EndTime {
				return
			}

			n, err := br.Read(buf)
			if err != nil && err != io.EOF {
				log.Println("read file err", err)
				break
			}

			// copy packet no.

			// copy data
			for i := 0; i < n; i++ {
				data[8+i] = buf[i]
			}

			if n < 512 {
				for i := 0; i < 512-n; i++ {
					data[8+n+i] = 0x00
				}
				keepGoing = false
			}

			for _, devID := range t.DevIDs {
				dev := ctx.DevCache[devID]
				if dev != nil && !dev.Locked {
					if dev.CurrentTask == nil {
						dev.CurrentTask = t
						dev.Send(data)
					} else {
						if dev.CurrentTask == t {
							dev.Send(data)
						} else {
							if t.Level <= dev.CurrentTask.Level && t.CreateTime > dev.CurrentTask.CreateTime {
								dev.CurrentTask = t
								dev.Send(data)
							}
						}
					}
				}
			}

			time.Sleep(time.Microsecond * 31250) // 31.25ms
		}
	}
}
